#include "game_scene.h"
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
Game_Scene::Game_Scene(Data_Manager *data_manager, QWidget *parent)
    :Scene_qt(parent),
    data_manager(data_manager)
{
    this->setWindowTitle("Game 游戏界面");


    setupMap();
    setupButton();

    setupMusic();
    setupPaintSystem();
    setupGameLogic();

    setupLabel();

    paintGrid();

    timer_update_game.setInterval(GAME_RATE);

    // 连接信号和槽函数：
    connect(&timer_update_game,&QTimer::timeout,this,&Game_Scene::update_game);
    connect(view,&View_qt::mouseMove,this,&Game_Scene::handle_mouseMove);
    connect(view,&View_qt::mouseWheel,this,&Game_Scene::handle_mouseWheel);
    connect(view,&View_qt::keyPress,this,&Game_Scene::handle_keyPress);
    // 获取金币
    connect(hub,&Hub::store,this,[=](int cnt)->void{
        this->data_manager->addGoldNum(cnt*data_manager->getInterestRate());
        this->storeedNum+=cnt;
        if(storeedNum >= targetNums){
            pointNum++;
            finishedTask++;
            storeedNum -= targetNums;
            targetNums = std::min(1000,targetNums*(2+finishedTask));
        }
        // qDebug() << cnt;
    });
}


// 初始化地图
void Game_Scene::setupMap(){

    QImage map_image(":/resource/img/map.png");
    QPixmap pix = QPixmap::fromImage(map_image.scaled(grid::EACH_MAP_LENGTH*BOX_LENTH,grid::EACH_MAP_LENGTH*BOX_LENTH));
    scene->setSceneRect(0,0,grid::WIDTH*BOX_LENTH,grid::HEIGHT*BOX_LENTH);
    for(int i = 0; i < grid::HEIGHT; i+=grid::EACH_MAP_LENGTH){
        qreal dy = i*BOX_LENTH;
        for(int j = 0; j < grid::WIDTH;j+=grid::EACH_MAP_LENGTH){
            qreal dx = j*BOX_LENTH;
            QGraphicsPixmapItem *pixmapItem = scene->addPixmap(pix);
            pixmapItem->moveBy(dx,dy);
        }
    }
    view->horizontalScrollBar()->setValue(
        (view->horizontalScrollBar()->maximum() - view->horizontalScrollBar()->minimum()) / 2);
    view->verticalScrollBar()->setValue(
        (view->verticalScrollBar()->maximum() - view->verticalScrollBar()->minimum()) / 2);

}

// 初始化下方/左边按钮
void Game_Scene::setupButton(){
    int btW = 46, btH = 46, interval = 8;

    FacilityIconButton *beltBtn = new FacilityIconButton(
        QString("%1/%2.png").arg(BUILDING_ICON_SRC).arg("belt"),
        3,btW,btH); // 组内有3个
    connect(beltBtn,&FacilityIconButton::clicked,this,[=]{chooseFacility(FacilityType::BELT,3);});

    FacilityIconButton *minerBtn = new FacilityIconButton(
        QString("%1/%2.png").arg(BUILDING_ICON_SRC).arg("miner"),
        1,btW,btH); // 组内有1个
    connect(minerBtn,&FacilityIconButton::clicked,this,[=]{chooseFacility(FacilityType::MINER,1);});

    FacilityIconButton *trashBtn = new FacilityIconButton(
        QString("%1/%2.png").arg(BUILDING_ICON_SRC).arg("trash"),
        1,btW,btH); // 组内有1个
    connect(trashBtn,&FacilityIconButton::clicked,this,[=]{chooseFacility(FacilityType::TRASH,1);});

    FacilityIconButton *cutterBtn = new FacilityIconButton(
        QString("%1/%2.png").arg(BUILDING_ICON_SRC).arg("cutter"),
        1,btW,btH); // 组内有1个
    connect(cutterBtn,&FacilityIconButton::clicked,this,[=]{chooseFacility(FacilityType::CUTTER,1);});

    FacilityIconButton *rotaterBtn = new FacilityIconButton(
        QString("%1/%2.png").arg(BUILDING_ICON_SRC).arg("rotater"),
        2,btW,btH); // 组内有2个
    connect(rotaterBtn,&FacilityIconButton::clicked,this,[=]{chooseFacility(FacilityType::ROTATER,2);});

    FacilityIconButton *balancerBtn = new FacilityIconButton(
        QString("%1/%2.png").arg(BUILDING_ICON_SRC).arg("balancer"),
        1,btW,btH); // 组内有1个
    connect(balancerBtn,&FacilityIconButton::clicked,this,[=]{chooseFacility(FacilityType::BALANCER,1);});

    iconBtns.append(QList<FacilityIconButton *>{beltBtn,minerBtn,cutterBtn,trashBtn,rotaterBtn,balancerBtn});

    // 画 button
    int st_pos_x = (this->width() - iconBtns.size()*(btW+interval)) / 2,
        st_pos_y = this->height() - btH - 30;
    for(int i = 0; i < iconBtns.size(); ++i){
        auto Btn = iconBtns[i];
        Btn->setParent(this);
        Btn->setFixedSize(btW, btH);
        Btn->move(st_pos_x + i*(btW+interval),st_pos_y);
    }

    QPushButton *upBtn_m = new QPushButton("升级\n开采器",this);
    connect(upBtn_m,&QPushButton::clicked,this,[=]{
        if(pointNum <= 0) return;
        --pointNum;
        this->game_logic->facility_manager->upgrate(0);
    });
    QPushButton *upBtn_t = new QPushButton("升级\n传送带",this);
    connect(upBtn_t,&QPushButton::clicked,this,[=]{
        if(pointNum <= 0) return;
        --pointNum;
        this->game_logic->facility_manager->upgrate(1);
    });
    QPushButton *upBtn_c = new QPushButton("升级\n裁剪器",this);
    connect(upBtn_c,&QPushButton::clicked,this,[=]{
        if(pointNum <= 0) return;
        --pointNum;
        this->game_logic->facility_manager->upgrate(2);
    });
    taskBtns.append(QList<QPushButton*>{upBtn_m,upBtn_t,upBtn_c});

    // 画 button
    int st_tpos_x = 0,
        st_tpos_y = (this->height() - taskBtns.size()*btH) / 2 - 30 ;
    for(int i = 0; i < taskBtns.size(); ++i){
        auto Btn = taskBtns[i];
        Btn->setParent(this);
        Btn->setFixedSize(btW, btH);
        Btn->move(st_tpos_x ,st_tpos_y + i*(btH+interval));
    }

}

// 初始化音乐
void Game_Scene::setupMusic(){
    this->audioOutput = new QAudioOutput(this);
    this->audioOutput->setVolume(0.5);
    this->player = new QMediaPlayer(this);
    this->player->setAudioOutput(audioOutput);
    this->player->setSource(QUrl("qrc:/resource/audio/DustAndAshes.ogg"));
    this->player->setLoops(-1);
}

// 初始化绘画系统
void Game_Scene::setupPaintSystem(){
    paint_system = new PaintSystem(this->scene);
}

// 初始化游戏逻辑
void Game_Scene::setupGameLogic(){
    game_logic = new GameLogic(this->data_manager,paint_system);
    this->my_mouse.chooseFacility(FacilityType::HUB,2,this->data_manager->getHubProgress());
    Coordinate co(grid::WIDTH / 2 - 1,grid::HEIGHT / 2 - 1);
    placeFacility(co);
    clearMouseItem();
    my_mouse.clear();
    hub = game_logic->facility_manager->hub;
}

// 画地图
void Game_Scene::paintGrid(){
    int ws,wd,hs,hd;
    switch(data_manager->getGridProgress()){
    case 0:
        ws = grid::WIDTH / 3;
        wd = 2 * grid::WIDTH / 3;
        hs = grid::HEIGHT / 3;
        hd = 2 * grid::HEIGHT / 3;

        break;
    case 1:
        ws = grid::WIDTH / 4;
        wd = 3 * grid::WIDTH / 4;
        hs = grid::HEIGHT / 4;
        hd = 3 * grid::HEIGHT / 4;
        break;
    case 2:
    default:
        ws = 0;
        wd = grid::WIDTH;
        hs = 0;
        hd = grid::HEIGHT;
        break;
    }
    auto &g = this->data_manager->getGrid();
    for(int i = ws; i < wd; ++i){
        for(int j = hs; j < hd; ++j){
            char cargo = g[i][j];
            if(cargo == '_'){continue;}
            QString s = QString("%1/%2.png").arg(STATIC_CARGO_SRC).arg(cargo);
            QImage image(s);
            image = image.scaled(BOX_LENTH*5/6,BOX_LENTH*5/6);
            QPixmap pix = QPixmap::fromImage(image);
            QGraphicsPixmapItem *item = scene->addPixmap(pix);
            item->setOffset(
                i*BOX_LENTH + BOX_LENTH / 12, j*BOX_LENTH + BOX_LENTH / 12
                );
            game_logic->grid->getBox(i,j).link_obj(item);
        }
    }
}

// 初始化Label
void Game_Scene::setupLabel(){
    pointNumLabel.setParent(this);
    pointNumLabel.setFixedSize(80, 40);
    pointNumLabel.setAlignment(Qt::AlignCenter);
    pointNumLabel.setText(QString("升级点数:%1").arg(pointNum));

    HubLabel.setParent(view);
    HubLabel.setFixedSize(100,80);
    HubLabel.setAlignment(Qt::AlignCenter);
    HubLabel.move(0, GAME_HEIGHT - 80);
    HubLabel.setText(QString("交付/目标:\n%1/%2").arg(storeedNum).arg(targetNums));
}

// 局内存档
void Game_Scene::do_save(){
    if(game_logic){game_logic->do_save();}
}

 // 局内读入
void Game_Scene::load_save(){

}

// 选择设备
void Game_Scene::chooseFacility(FacilityType f_type, int groupNum){
    this->my_mouse.chooseFacility(f_type,groupNum);
    this->updateMouseItem();
}

// 鼠标更改组内号
void Game_Scene::chageFacilityIdx(){
    this->my_mouse.changeIdx();
    this->updateMouseItem();
}

// 放置设备
void Game_Scene::placeFacility(Coordinate co){
    // 根据 dir
    // 从逻辑层 加入
    Facility* facility = game_logic->tryToPlaceFacility(
        my_mouse.f_type,my_mouse.f_dir,my_mouse.groupIdx,co);
    // 如果ok 绘图
    if(facility){
        // paint
        QImage image = my_mouse.mouse_pix.toImage();
        QPixmap pix = QPixmap::fromImage(image.scaled(image.width()*16.0/15,image.height()*16.0/15));
        Object_Qt * item = scene->addPixmap(pix);
        item->setOffset(co.x*BOX_LENTH,co.y*BOX_LENTH);
        // 设置渲染层
        if(my_mouse.f_type == FacilityType::BELT){item->setZValue(BELT_LEVEL);}
        else{item->setZValue(NORMAL_FACILITY_LEVEL);}
        // 连接item
        facility->linkObject(item);
    }
    // clearMouseItem(); 不清空 就直接可以连续放置
}

// 删除设备
void Game_Scene::removeFacility(Coordinate co){
    game_logic->tryToRemoveFacility(co);
    my_mouse.clear();
}

// 进入场景
void Game_Scene::enterScene(){
    this->show();
    // mouse track
    setMouseTracking(true);
    centralWidget()->setMouseTracking(true);
    timer_update_game.start();  // 启动定时器
    this->player->play();
}

// 退出游戏场景
void Game_Scene::leaveScene(){
    // mouse track
    clearMouseItem();
    this->my_mouse.clear();
    this->player->stop();
    setMouseTracking(false);
    centralWidget()->setMouseTracking(false);
    timer_update_game.stop();  // 终止定时器
    this->hide();
}

// 更新鼠标携带的item
void Game_Scene::updateMouseItem(){
    if(item) clearMouseItem();
    if(this->my_mouse.isempty()) return;
    item = scene->addPixmap(this->my_mouse.mouse_pix);
    item->setOffset(mousePos.x()-20,mousePos.y()-20);
    item->setZValue(MOUSE_ITEM_LEVEL);
}

// 更新游戏帧
void Game_Scene::update_game(){

    game_logic->logic_update();
    update();
}

// 绘图事件
void Game_Scene::paintEvent(QPaintEvent *){

    if(item && !this->my_mouse.isempty()){
        item->setOffset(mousePos.x()-20,mousePos.y()-20);
    }
    // Label
    pointNumLabel.setText(QString("升级点数:%1").arg(pointNum));
    HubLabel.setText(QString("交付/目标:\n%1/%2").arg(storeedNum).arg(targetNums));
}

// 鼠标点击事件
void Game_Scene::mousePressEvent(QMouseEvent *event){
    if(event->buttons() & Qt::LeftButton){ // 左击 创建
        if(item && !my_mouse.isempty()){
            this->placeFacility(QPointFToCoordinate(
                mousePos.x(),
                mousePos.y())
                );
        }
    }
    else if(event->buttons() & Qt::RightButton){ // 右击 删除
        if(item && !my_mouse.isempty()){
            my_mouse.clear();
            this->clearMouseItem(); // 删除携带
        }
        else{ // 尝试删除坐标
            this->removeFacility(QPointFToCoordinate(mousePos.x(),mousePos.y()));
        }
        my_mouse.clear();
        this->clearMouseItem(); // 删除携带
    }
    handle_mouseMove(event); // 更新鼠标坐标
}

// 键盘按下事件
void Game_Scene::keyPressEvent(QKeyEvent *event){
    /// R 为旋转
    /// T 为组内Next
    if (!event->isAutoRepeat() && !process) {
        if(this->my_mouse.isempty()){return;}
        process = true;
        switch (event->key()) {
        case Qt::Key_R:
            this->my_mouse.changeDir();
            updateMouseItem();
            break;
        case Qt::Key_T:
            this->chageFacilityIdx();
            break;
        default:
            break;
        }
        process = false;
    }
    handle_keyPress(event);
}

// 鼠标移动事件
void Game_Scene::mouseMoveEvent(QMouseEvent *event) {
    this->handle_mouseMove(event);
}

// 处理鼠标移动事件
void Game_Scene:: handle_mouseMove(QMouseEvent *event){
    mousePos = view->mapToScene(event->pos());
    updateMouseItem();
}

// 处理鼠标滚轮事件
void Game_Scene:: handle_mouseWheel(QWheelEvent *event){
    mousePos = view->mapToScene(event->position().x(),event->position().y());

    update();
}

void Game_Scene:: handle_keyPress(QKeyEvent *event){
    // update();
}

Game_Scene::~Game_Scene(){
    clearMouseItem();
    for(int i = 0; i < iconBtns.size(); ++i){
        if(iconBtns[i]){delete iconBtns[i];}
    }
    for(int i = 0; i < taskBtns.size(); ++i){
        if(taskBtns[i]){delete taskBtns[i];}
    }
    if(game_logic) {delete game_logic; game_logic = null;}
    if(paint_system) {delete paint_system; paint_system = null;}
    if(player) {this->player->stop();delete player; player = null;}
    if(audioOutput) {delete audioOutput; audioOutput = null;}
}
